```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>深入解析Guava Cache源码 - Java本地缓存的艺术</title>
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            color: #333;
            line-height: 1.8;
        }
        h1, h2, h3, h4 {
            font-family: 'Noto Serif SC', serif;
            font-weight: 600;
        }
        .hero-gradient {
            background: linear-gradient(135deg, #6e8efb 0%, #a777e3 100%);
        }
        .code-block {
            background-color: #2d2d2d;
            color: #f8f8f2;
            border-radius: 8px;
            overflow-x: auto;
        }
        .highlight-card {
            transition: all 0.3s ease;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }
        .highlight-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
        }
        .section-divider {
            height: 1px;
            background: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgba(167,119,227,0.5) 50%, rgba(0,0,0,0) 100%);
        }
        .first-letter::first-letter {
            float: left;
            font-size: 3em;
            line-height: 0.8;
            margin-right: 0.2em;
            color: #6e8efb;
            font-family: 'Noto Serif SC', serif;
        }
    </style>
</head>
<body class="bg-gray-50">
    <!-- Hero Section -->
    <section class="hero-gradient text-white py-20 px-4 md:px-0">
        <div class="container mx-auto max-w-4xl">
            <div class="flex flex-col items-center text-center">
                <div class="text-4xl md:text-6xl font-bold mb-4 animate-fade-in">
                    <span class="text-yellow-200">Guava Cache</span> 源码深度解析
                </div>
                <div class="text-xl md:text-2xl mb-8 font-light opacity-90">
                    Google工程师如何实现优雅的本地缓存解决方案
                </div>
                <div class="w-24 h-1 bg-yellow-200 mb-8 rounded-full"></div>
                <div class="text-lg md:text-xl max-w-2xl leading-relaxed first-letter">
                    在我十多年的Java开发生涯中，Guava的Cache可能是我用过的最让人省心的本地缓存实现了。没有之一。今天咱们就来扒一扒它的源码，看看Google工程师是怎么把这个看似简单的功能实现得这么优雅的。
                </div>
            </div>
        </div>
    </section>

    <!-- Main Content -->
    <main class="container mx-auto max-w-4xl px-4 md:px-0 py-12">
        <!-- 为什么需要本地缓存 -->
        <section class="mb-16">
            <div class="flex items-center mb-8">
                <div class="text-3xl font-bold text-gray-800">1. 为什么需要本地缓存？</div>
                <div class="ml-4 text-purple-500 text-2xl"><i class="fas fa-question-circle"></i></div>
            </div>
            <div class="bg-white rounded-lg p-6 shadow-md mb-6">
                <p class="text-lg mb-4">在日常开发中，我们经常会遇到需要频繁获取相同数据的场景。比如：</p>
                <ul class="list-disc pl-8 mb-6 space-y-2">
                    <li><span class="font-medium">配置信息读取</span></li>
                    <li><span class="font-medium">重复计算的结果缓存</span></li>
                    <li><span class="font-medium">数据库查询结果缓存</span></li>
                    <li><span class="font-medium">远程服务调用结果缓存</span></li>
                </ul>
                <p class="text-lg mb-4">如果每次都从原始数据源获取，不仅效率低下，还会给底层系统带来不必要的压力。本地缓存就是为解决这类问题而生的。</p>
                <p class="text-lg">Guava Cache提供了一种高效、线程安全的本地缓存解决方案，它介于手动实现的HashMap和分布式缓存(如Redis)之间，非常适合单机环境下的缓存需求。</p>
            </div>
            
            <div class="bg-blue-50 border-l-4 border-blue-500 p-4 rounded-r-lg">
                <div class="flex items-start">
                    <div class="flex-shrink-0 text-blue-500 text-xl mr-2 mt-1"><i class="fas fa-lightbulb"></i></div>
                    <div>
                        <h4 class="text-lg font-semibold text-blue-800 mb-2">关键洞察</h4>
                        <p class="text-blue-700">Guava Cache的巧妙之处在于它平衡了性能与易用性，提供了丰富的功能同时保持了API的简洁性。这种设计哲学值得每个Java开发者学习。</p>
                    </div>
                </div>
            </div>
        </section>

        <div class="section-divider my-12"></div>

        <!-- LoadingCache实现原理与淘汰策略 -->
        <section class="mb-16">
            <div class="flex items-center mb-8">
                <div class="text-3xl font-bold text-gray-800">2. LoadingCache实现原理与淘汰策略</div>
                <div class="ml-4 text-purple-500 text-2xl"><i class="fas fa-microscope"></i></div>
            </div>

            <!-- 核心接口设计 -->
            <div class="mb-10">
                <h3 class="text-2xl font-semibold mb-4 text-gray-700">2.1 核心接口设计</h3>
                <div class="bg-white rounded-lg p-6 shadow-md mb-6">
                    <p class="text-lg mb-4">Guava Cache的核心是<code class="bg-gray-100 px-2 py-1 rounded">Cache</code>接口，它定义了缓存的基本操作：</p>
                    <div class="code-block p-4 mb-6">
                        <pre><code class="language-java">public interface Cache&lt;K, V&gt; {
  V getIfPresent(Object key);
  V get(K key, Callable&lt;? extends V&gt; valueLoader);
  void put(K key, V value);
  void invalidate(Object key);
  // 其他方法...
}</code></pre>
                    </div>
                    <p class="text-lg mb-4">而<code class="bg-gray-100 px-2 py-1 rounded">LoadingCache</code>是它的扩展，增加了自动加载值的能力：</p>
                    <div class="code-block p-4 mb-4">
                        <pre><code class="language-java">public interface LoadingCache&lt;K, V&gt; extends Cache&lt;K, V&gt; {
  V get(K key) throws ExecutionException;
  ImmutableMap&lt;K, V&gt; getAll(Iterable&lt;? extends K&gt; keys) throws ExecutionException;
  // 其他方法...
}</code></pre>
                    </div>
                    <p class="text-lg">说实话，这个接口设计非常优雅，既保留了基本缓存的核心功能，又通过扩展提供了更高级的特性。这也是为什么后来的Caffeine等缓存库在API设计上多少都有Guava Cache的影子。</p>
                </div>
            </div>

            <!-- 数据结构与存储机制 -->
            <div class="mb-10">
                <h3 class="text-2xl font-semibold mb-4 text-gray-700">2.2 数据结构与存储机制</h3>
                <div class="bg-white rounded-lg p-6 shadow-md mb-6">
                    <p class="text-lg mb-4">深入源码会发现，Guava Cache的底层存储结构是一个基于分段锁的并发哈希表（类似于JDK 7中的ConcurrentHashMap实现）。</p>
                    <div class="code-block p-4 mb-6">
                        <pre><code class="language-java">// LocalCache.java (简化版)
class LocalCache&lt;K, V&gt; {
  final int segmentMask;
  final Segment&lt;K, V&gt;[] segments;
  
  // ...其他字段和方法
}

static class Segment&lt;K, V&gt; extends ReentrantLock {
  volatile int count;
  int threshold;
  AtomicReferenceArray&lt;ReferenceEntry&lt;K, V&gt;&gt; table;
  
  // ...其他字段和方法
}</code></pre>
                    </div>
                    <p class="text-lg">每个Segment维护一个散列表，并通过独立的锁控制并发访问，这种设计巧妙地平衡了并发性能与内存占用。在我实际项目中，曾经遇到过高并发下大量线程同时读写缓存的场景，传统的HashMap+同步块方案性能惨不忍睹，而换成Guava Cache后，吞吐量提升了接近10倍！这种分段锁设计在当时看来简直是救命稻草。</p>
                </div>
            </div>

            <!-- 缓存淘汰策略 -->
            <div class="mb-10">
                <h3 class="text-2xl font-semibold mb-4 text-gray-700">2.3 缓存淘汰策略</h3>
                <div class="bg-white rounded-lg p-6 shadow-md mb-6">
                    <p class="text-lg mb-4">Guava Cache支持多种淘汰策略，主要包括：</p>
                    <ol class="list-decimal pl-8 mb-6 space-y-3">
                        <li><span class="font-medium">基于容量的淘汰</span>：当缓存数量达到上限时，淘汰最近最少使用的条目</li>
                        <li><span class="font-medium">基于时间的淘汰</span>：
                            <ul class="list-disc pl-6 mt-2">
                                <li>访问后过期：条目在最后一次访问后的一段时间后过期</li>
                                <li>写入后过期：条目在写入后的一段时间后过期</li>
                            </ul>
                        </li>
                        <li><span class="font-medium">基于引用的淘汰</span>：
                            <ul class="list-disc pl-6 mt-2">
                                <li>使用软引用存储值</li>
                                <li>使用弱引用存储键或值</li>
                            </ul>
                        </li>
                    </ol>
                    <p class="text-lg mb-4">淘汰的具体实现依赖于记录访问顺序的链表结构和定时清理机制。每个缓存条目(ReferenceEntry)都会记录其访问信息，用于淘汰决策。</p>
                    <p class="text-lg mb-4">下面是一个典型的缓存配置示例：</p>
                    <div class="code-block p-4">
                        <pre><code class="language-java">// 构建一个复杂的缓存示例
LoadingCache&lt;Key, Value&gt; cache = CacheBuilder.newBuilder()
    .maximumSize(10000)                  // 最大容量
    .expireAfterWrite(10, TimeUnit.MINUTES) // 写入后10分钟过期
    .expireAfterAccess(5, TimeUnit.MINUTES) // 访问后5分钟过期
    .removalListener(notification -&gt; {    // 移除监听器
        System.out.println("Key " + notification.getKey() + " was removed due to " + notification.getCause());
    })
    .recordStats()                       // 记录统计信息
    .build(new CacheLoader&lt;Key, Value&gt;() {  // 定义数据加载器
        @Override
        public Value load(Key key) throws Exception {
            return loadValueFromDb(key);  // 从数据库加载
        }
    });</code></pre>
                    </div>
                </div>
            </div>
        </section>

        <div class="section-divider my-12"></div>

        <!-- 缓存加载机制与回收机制源码分析 -->
        <section class="mb-16">
            <div class="flex items-center mb-8">
                <div class="text-3xl font-bold text-gray-800">3. 缓存加载机制与回收机制源码分析</div>
                <div class="ml-4 text-purple-500 text-2xl"><i class="fas fa-code"></i></div>
            </div>

            <!-- CacheLoader的工作原理 -->
            <div class="mb-10">
                <h3 class="text-2xl font-semibold mb-4 text-gray-700">3.1 CacheLoader的工作原理</h3>
                <div class="bg-white rounded-lg p-6 shadow-md mb-6">
                    <p class="text-lg mb-4">LoadingCache的核心在于CacheLoader，它定义了缓存未命中时如何加载值：</p>
                    <div class="code-block p-4 mb-6">
                        <pre><code class="language-java">public abstract class CacheLoader&lt;K, V&gt; {
  public abstract V load(K key) throws Exception;
  
  // 批量加载方法，默认实现是逐个调用load
  public Map&lt;K, V&gt; loadAll(Iterable&lt;? extends K&gt; keys) throws Exception {
    Map&lt;K, V&gt; result = Maps.newLinkedHashMap();
    for (K key : keys) {
      result.put(key, load(key));
    }
    return result;
  }
  
  // 静态工厂方法
  public static &lt;K, V&gt; CacheLoader&lt;K, V&gt; from(Function&lt;K, V&gt; function) {
    return new FunctionToCacheLoader&lt;&gt;(function);
  }
}</code></pre>
                    </div>
                    <p class="text-lg mb-4">这个抽象类设计得很巧妙，只需要实现单个key的load方法，就能自动支持批量加载功能。而且还提供了便捷的静态工厂方法，支持从Function直接创建CacheLoader。</p>
                    <p class="text-lg mb-4">LoadingCache的get方法处理逻辑大致如下：</p>
                    <ol class="list-decimal pl-8 mb-6 space-y-2">
                        <li>检查缓存中是否已存在该键的有效条目</li>
                        <li>如果不存在，则锁定该键的加载操作</li>
                        <li>通过CacheLoader加载值</li>
                        <li>将加载的值放入缓存</li>
                        <li>返回加载的值</li>
                    </ol>
                    <p class="text-lg">从源码实现看，Guava还做了很多优化，比如确保同一个key不会并发加载多次（通过Future实现），这在高并发场景下非常重要。</p>
                </div>
            </div>

            <!-- 回收机制实现分析 -->
            <div class="mb-10">
                <h3 class="text-2xl font-semibold mb-4 text-gray-700">3.2 回收机制实现分析</h3>
                <div class="bg-white rounded-lg p-6 shadow-md mb-6">
                    <p class="text-lg mb-4">缓存的回收主要分为主动回收和被动回收两种：</p>
                    <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
                        <div class="highlight-card bg-white border border-gray-200 rounded-lg p-6 shadow-sm">
                            <div class="flex items-center mb-4">
                                <div class="bg-blue-100 p-2 rounded-full mr-4">
                                    <i class="fas fa-sync-alt text-blue-600 text-xl"></i>
                                </div>
                                <h4 class="text-xl font-semibold text-gray-800">被动回收</h4>
                            </div>
                            <p class="text-gray-700">当尝试获取缓存值时，顺便检查缓存条目是否过期，如果过期则回收。</p>
                        </div>
                        <div class="highlight-card bg-white border border-gray-200 rounded-lg p-6 shadow-sm">
                            <div class="flex items-center mb-4">
                                <div class="bg-purple-100 p-2 rounded-full mr-4">
                                    <i class="fas fa-broom text-purple-600 text-xl"></i>
                                </div>
                                <h4 class="text-xl font-semibold text-gray-800">主动回收</h4>
                            </div>
                            <p class="text-gray-700">通过专门的清理线程定期清理过期条目。</p>
                        </div>
                    </div>
                    <p class="text-lg mb-4">在LocalCache.java中有一个关键方法<code class="bg-gray-100 px-2 py-1 rounded">cleanUp()</code>：</p>
                    <div class="code-block p-4 mb-6">
                        <pre><code class="language-java">// LocalCache.java (简化)
void cleanUp() {
  for (Segment&lt;K, V&gt; segment : segments) {
    segment.cleanUp();
  }
}

// Segment类中
void cleanUp() {
  runCleanup(expiredEntries());
}

void runCleanup(Queue&lt;ReferenceEntry&lt;K, V&gt;&gt; taskQueue) {
  long now = ticker.read();
  ReferenceEntry&lt;K, V&gt; e;
  int i = 0;
  while ((e = taskQueue.poll()) != null) {
    removeEntry(e, e.getHash(), RemovalCause.EXPIRED);
    if (++i == CLEANUP_BATCH_SIZE) {
      break;
    }
  }
}</code></pre>
                    </div>
                    <p class="text-lg mb-4">清理操作分批进行，避免一次清理过多条目导致长时间占用锁。这种批量清理的设计在其他缓存实现中也被广泛采用。</p>
                    <p class="text-lg">有一点很多人容易忽略：Guava Cache并不保证过期条目会立即被清除！它只保证：</p>
                    <ol class="list-decimal pl-8 mt-4 space-y-2">
                        <li>写入后过期的条目在到期后，获取时会返回null</li>
                        <li>访问后过期的条目在一定时间不访问后，会被清理线程回收</li>
                    </ol>
                    <div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 rounded-r-lg mt-6">
                        <div class="flex items-start">
                            <div class="flex-shrink-0 text-yellow-500 text-xl mr-2 mt-1"><i class="fas fa-exclamation-triangle"></i></div>
                            <div>
                                <h4 class="text-lg font-semibold text-yellow-800 mb-2">性能陷阱</h4>
                                <p class="text-yellow-700">我在做性能优化时就遇到过这个"陷阱"，以为设置了过期时间就一定会准时清理，结果因为没有显式调用cleanUp()，导致内存占用一直居高不下。</p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <div class="section-divider my-12"></div>

        <!-- CacheBuilder设计模式与链式调用实现 -->
        <section class="mb-16">
            <div class="flex items-center mb-8">
                <div class="text-3xl font-bold text-gray-800">4. CacheBuilder设计模式与链式调用实现</div>
                <div class="ml-4 text-purple-500 text-2xl"><i class="fas fa-wrench"></i></div>
            </div>

            <div class="bg-white rounded-lg p-6 shadow-md mb-6">
                <p class="text-lg mb-4">CacheBuilder是Guava Cache的入口，采用了经典的建造者模式(Builder Pattern)，通过流畅的链式API创建复杂的缓存配置。</p>
                
                <h3 class="text-2xl font-semibold mb-4 text-gray-700 mt-8">4.1 Builder模式的优势</h3>
                <p class="text-lg mb-4">相比传统的构造函数或工厂方法，Builder模式的优势非常明显：</p>
                <ul class="list-disc pl-8 mb-6 space-y-2">
                    <li><span class="font-medium">可读性</span>：每个方法调用明确表达一个配置项</li>
                    <li><span class="font-medium">可维护性</span>：新增配置不需要修改已有构造函数</li>
                    <li><span class="font-medium">参数验证</span>：每个方法可以独立验证参数</li>
                    <li><span class="font-medium">默认值</span>：自动应用合理的默认值</li>
                </ul>
                <p class="text-lg mb-4">试想如果用构造函数来配置Guava Cache，可能会是这样：</p>
                <div class="code-block p-4 mb-6">
                    <pre><code class="language-java">// 假设用构造函数配置（实际Guava不是这样实现的）
Cache&lt;String, Object&gt; cache = new Cache&lt;&gt;(
    10000,           // 最大容量
    0,               // 最大权重（不使用）
    true,            // 是否记录访问顺序
    true,            // 是否记录写入顺序
    10,              // 写入后过期时间
    TimeUnit.MINUTES,// 写入过期时间单位
    5,               // 访问后过期时间
    TimeUnit.MINUTES,// 访问过期时间单位 
    null,            // 移除监听器
    false            // 是否记录统计信息
);</code></pre>
                </div>
                <p class="text-lg mb-4">这谁看得懂？而使用Builder模式：</p>
                <div class="code-block p-4 mb-6">
                    <pre><code class="language-java">Cache&lt;String, Object&gt; cache = CacheBuilder.newBuilder()
    .maximumSize(10000)
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .expireAfterAccess(5, TimeUnit.MINUTES)
    .build();</code></pre>
                </div>
                <p class="text-lg">简洁明了，不是吗？</p>
                
                <h3 class="text-2xl font-semibold mb-4 text-gray-700 mt-8">4.2 CacheBuilder源码分析</h3>
                <p class="text-lg mb-4">CacheBuilder的实现精髓在于每个配置方法都返回this，实现链式调用：</p>
                <div class="code-block p-4 mb-6">
                    <pre><code class="language-java">// CacheBuilder.java (简化)
public CacheBuilder&lt;K, V&gt; maximumSize(long size) {
  checkState(maximumWeight == UNSET_INT, "maximumWeight already set");
  checkArgument(size >= 0, "maximum size must not be negative");
  this.maximumSize = size;
  return this;
}

public CacheBuilder&lt;K, V&gt; expireAfterWrite(long duration, TimeUnit unit) {
  checkState(expireAfterWriteNanos == UNSET_INT, "expireAfterWrite already set");
  checkArgument(duration >= 0, "duration cannot be negative");
  this.expireAfterWriteNanos = unit.toNanos(duration);
  return this;
}</code></pre>
                </div>
                <p class="text-lg mb-4">每个方法都做了参数验证和状态检查，确保配置的一致性。最终，build()方法根据收集的配置创建具体的Cache实例：</p>
                <div class="code-block p-4 mb-6">
                    <pre><code class="language-java">// CacheBuilder.java (简化)
public &lt;K1 extends K, V1 extends V&gt; Cache&lt;K1, V1&gt; build() {
  checkWeightWithMaximumSize();
  
  LocalCache&lt;K1, V1&gt; localCache = new LocalCache&lt;&gt;(this);
  return localCache.isLoading() ? new LoadingCache&lt;&gt;(localCache) : new Cache&lt;&gt;(localCache);
}</code></pre>
                </div>
                <p class="text-lg">CacheBuilder还提供了很多静态工厂方法，比如：</p>
                <div class="code-block p-4 mt-4">
                    <pre><code class="language-java">// 从系统配置创建
CacheBuilder.from(CacheBuilderSpec.parse("maximumSize=10000,expireAfterWrite=10m"));

// 从字符串配置创建
CacheBuilder.from("maximumSize=10000,expireAfterWrite=10m");</code></pre>
                </div>
                <p class="text-lg mt-4">这种灵活性使得Guava Cache可以轻松地通过配置文件进行配置，特别适合需要动态调整缓存参数的场景。</p>
            </div>
        </section>

        <div class="section-divider my-12"></div>

        <!-- 实战案例：高性能API缓存实现 -->
        <section class="mb-16">
            <div class="flex items-center mb-8">
                <div class="text-3xl font-bold text-gray-800">5. 实战案例：高性能API缓存实现</div>
                <div class="ml-4 text-purple-500 text-2xl"><i class="fas fa-laptop-code"></i></div>
            </div>

            <div class="bg-white rounded-lg p-6 shadow-md mb-6">
                <p class="text-lg mb-4">来看一个我在实际项目中使用的例子。这是一个API响应缓存，用于缓存外部API的调用结果，减少重复请求：</p>
                <div class="code-block p-4 mb-6">
                    <pre><code class="language-java">public class ApiResponseCache {
    private final LoadingCache&lt;ApiRequest, ApiResponse&gt; cache;
    
    public ApiResponseCache(ApiClient apiClient) {
        // 构建缓存
        this.cache = CacheBuilder.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(5, TimeUnit.MINUTES) // API响应缓存5分钟
            .recordStats() // 启用统计
            .removalListener(notification -&gt; {
                if (notification.getCause() == RemovalCause.EXPIRED) {
                    log.info("API缓存过期: {}", notification.getKey());
                }
            })
            .build(new CacheLoader&lt;ApiRequest, ApiResponse&gt;() {
                @Override
                public ApiResponse load(ApiRequest request) throws Exception {
                    log.info("缓存未命中，调用API: {}", request);
                    return apiClient.call(request);
                }
            });
    }
    
    public ApiResponse getResponse(ApiRequest request) {
        try {
            return cache.get(request);
        } catch (ExecutionException e) {
            log.error("获取API响应失败", e);
            throw new RuntimeException("API调用异常", e.getCause());
        }
    }
    
    // 获取缓存统计信息
    public CacheStats getStats() {
        return cache.stats();
    }
    
    // 清空缓存
    public void invalidateAll() {
        cache.invalidateAll();
    }
}</code></pre>
                </div>
                <p class="text-lg">使用这个缓存后，原本平均响应时间200ms的API接口，在缓存命中的情况下响应时间降到了不到1ms，系统整体吞吐量提升了5倍多。最让我惊喜的是，即使在高并发场景下（每秒数千请求），Guava Cache也保持了出色的性能，并没有成为系统瓶颈。这要归功于它精心设计的并发机制。</p>
            </div>
        </section>

        <!-- 概念关系图 -->
        <section class="mb-16">
            <div class="flex items-center mb-8">
                <div class="text-3xl font-bold text-gray-800">Guava Cache 核心概念关系图</div>
                <div class="ml-4 text-purple-500 text-2xl"><i class="fas fa-project-diagram"></i></div>
            </div>
            <div class="bg-white rounded-lg p-6 shadow-md">
                <div class="mermaid">
                    graph TD
                    A[CacheBuilder] -->|构建| B(LoadingCache)
                    B --> C[Cache]
                    C --> D[LocalCache]
                    D --> E[Segments]
                    E --> F[ReferenceEntry]
                    F --> G[Key-Value对]
                    A --> H[配置参数]
                    H --> I[最大容量]
                    H --> J[过期策略]
                    H --> K[移除监听器]
                    H --> L[统计信息]
                    B --> M[CacheLoader]
                    M --> N[自动加载机制]
                </div>
            </div>
        </section>
    </main>

    <!-- Footer -->
    <footer class="bg-gray-900 text-gray-300 py-8">
        <div class="container mx-auto max-w-4xl px-4 text-center">
            <div class="mb-4">
                <div class="text-xl font-medium text-white mb-2">技术小馆</div>
                <a href="http://www.yuque.com/jtostring" class="text-blue-400 hover:text-blue-300 transition duration-300">http://www.yuque.com/jtostring</a>
            </div>
            <div class="text-sm">© 2023 技术小馆. 保留所有权利.</div>
        </div>
    </footer>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'dark',
            flowchart: {
                useMaxWidth: false,
                htmlLabels: true,
                curve: 'basis'
            }
        });
    </script>
</body>
</html>
```